package iit.projects.etaxi.model.service;

import iit.projects.etaxi.model.exception.base.ErrorException;
import iit.projects.etaxi.model.exception.base.FatalException;
import iit.projects.etaxi.model.exception.base.InfoException;
import iit.projects.etaxi.model.exception.base.WarnException;
import iit.projects.etaxi.util.JSFUtils;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ServiceInvocationHandler implements InvocationHandler {

	private Object obj;

	private final Log log = LogFactory.getLog(ServiceInvocationHandler.class);

	public ServiceInvocationHandler(Object obj) {
		this.obj = obj;
	}

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		try {
			try {
				return method.invoke(obj, args);
			} catch (InvocationTargetException e) {
				Throwable throwable = e.getTargetException();
				throw throwable;
			}
		} catch (Throwable e) {
			log.error("Throwable caught from ServiceInvocationHandler.", e);

			FacesContext context = FacesContext.getCurrentInstance();

			FacesMessage facesMessage;
			Object[] exceptionArgs;

			if (e instanceof ErrorException) {
				ErrorException errorException = (ErrorException) e;
				exceptionArgs = errorException.getArgs();
				if (exceptionArgs != null) {
					facesMessage = JSFUtils.getMessageFromBundleWithArgs(e.getClass().getName(), FacesMessage.SEVERITY_ERROR,
							exceptionArgs);
				} else {
					facesMessage = JSFUtils.getMessageFromBundle(e.getClass().getName(), FacesMessage.SEVERITY_ERROR);
				}
			} else if (e instanceof FatalException) {
				FatalException fatalException = (FatalException) e;
				exceptionArgs = fatalException.getArgs();
				if (exceptionArgs != null) {
					facesMessage = JSFUtils.getMessageFromBundleWithArgs(e.getClass().getName(), FacesMessage.SEVERITY_FATAL,
							exceptionArgs);
				} else {
					facesMessage = JSFUtils.getMessageFromBundle(e.getClass().getName(), FacesMessage.SEVERITY_FATAL);
				}
			} else if (e instanceof InfoException) {
				InfoException infoException = (InfoException) e;
				exceptionArgs = infoException.getArgs();
				if (exceptionArgs != null) {
					facesMessage = JSFUtils.getMessageFromBundleWithArgs(e.getClass().getName(), FacesMessage.SEVERITY_INFO,
							exceptionArgs);
				} else {
					facesMessage = JSFUtils.getMessageFromBundle(e.getClass().getName(), FacesMessage.SEVERITY_INFO);
				}
			} else if (e instanceof WarnException) {
				WarnException warnException = (WarnException) e;
				exceptionArgs = warnException.getArgs();
				if (exceptionArgs != null) {
					facesMessage = JSFUtils.getMessageFromBundleWithArgs(e.getClass().getName(), FacesMessage.SEVERITY_WARN,
							exceptionArgs);
				} else {
					facesMessage = JSFUtils.getMessageFromBundle(e.getClass().getName(), FacesMessage.SEVERITY_WARN);
				}
			} else {
				facesMessage = JSFUtils.getMessageFromBundle(e.getClass().getName(), FacesMessage.SEVERITY_FATAL);
				if (facesMessage.getSummary().startsWith(JSFUtils.NO_RESOURCE_FOUND)) {
					facesMessage = JSFUtils.getMessageFromBundle("exception.general", FacesMessage.SEVERITY_FATAL);
				}
			}

			context.addMessage(null, facesMessage);
			throw e;
		}
	}
	

}
